package com.wxzz.elearing.comment.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wxzz.elearing.comment.amqp.producer.CommentProducer;
import com.wxzz.elearing.comment.dto.SkillCommentDto;
import com.wxzz.elearing.comment.dto.SkillDto;
import com.wxzz.elearing.comment.dto.SkillPublishDto;
import com.wxzz.elearing.comment.entity.Skill;
import com.wxzz.elearing.comment.entity.SkillCenterCategory;
import com.wxzz.elearing.comment.entity.SkillComment;
import com.wxzz.elearing.comment.entity.SkillVideoLog;
import com.wxzz.elearing.comment.mapper.SkillCenterCategoryMapper;
import com.wxzz.elearing.comment.mapper.SkillMapper;
import com.wxzz.elearing.comment.mapper.SkillVideoLogMapper;
import com.wxzz.elearing.comment.service.ISkillService;
import com.wxzz.elearing.comment.service.openfeign.IWxUserApiFeign;
import com.wxzz.elearing.comment.vo.SkillPublishVo;
import com.wxzz.elearing.comment.vo.SkillVo;
import com.wxzz.elearning.common.dto.FeignWxUserDto;
import com.wxzz.elearning.common.dto.SystemMessageMqDto;
import com.wxzz.elearning.common.dto.WxUserDto;
import com.wxzz.elearning.common.exception.ServiceException;
import com.wxzz.elearning.common.utils.OpenFeignUtil;
import com.wxzz.elearning.common.vo.JgPageVo;
import com.wxzz.elearning.common.vo.ReturnVO;
import io.seata.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 技能 服务实现类
 * </p>
 *
 * @author
 * @since 2021-05-17
 */
@Service
@Slf4j
public class SkillServiceImpl extends ServiceImpl<SkillMapper, Skill> implements ISkillService {

    @Autowired
    SkillMapper skillMapper;

    @Autowired
    SkillCenterCategoryMapper skillCenterCategoryMapper;

    @Autowired
    SkillVideoLogMapper skillVideoLogMapper;

    @Autowired
    IWxUserApiFeign wxUserApiFeign;

    @Autowired
    public MongoTemplate mongoTemplate;

    @Override
    public ReturnVO saveSkill(Skill skill) {

        SkillCenterCategory category = skillCenterCategoryMapper.selectById(skill.getCategoryId());
        if (category==null)
            throw new ServiceException("请填写正确的技能分类[1000]");
        if (!category.getEnterpriseId().equals(skill.getEnterpriseId()))
            throw new ServiceException("请填写正确的技能分类[1001]");

        // check skillType 0-技能沉淀 1-技能中心
        if (skill.getSkillType()==0){
            if (StringUtils.isNullOrEmpty(skill.getSkillVideoUrl())) throw new ServiceException("请填写技能视频");
        }else{
            if (StringUtils.isNullOrEmpty(skill.getSkillContent())) throw new ServiceException("请填写技能文章");
        }
        if (skill.getId() == null) {
            skill.setCheckStatus(0);
            skillMapper.insert(skill);
        } else {
            skillMapper.updateById(skill);
        }
        return new ReturnVO("操作成功", skill.getId());
    }

    @Override
    public ReturnVO checkSkill(Long id, Integer checkStatus, Boolean isBackend) {
        Skill skillInfo = skillMapper.selectById(id);
        if (skillInfo==null)
            throw new ServiceException("请选择正确的技能");

        // TODO: 判断是否是后台操作 如果是前端操作 则需要检查是否是部门用户

        Skill saveObj = new Skill();
        saveObj.setId( skillInfo.getId() );
        saveObj.setCheckStatus( checkStatus );
        return new ReturnVO("操作成功","");
    }

    @Override
    @Transactional
    public ReturnVO<SkillVo> selectSkillDetail(Long id, Long enterpriseId, Long userId) {
        Skill skillInfo = skillMapper.selectById(id);
        if (skillInfo==null) {
            throw new ServiceException("请选择正确的技能");
        }
//        if (!enterpriseId.equals(skillInfo.getEnterpriseId())) {
//            throw new ServiceException("当前没有查看的权限");
//        }

        SkillVo vo = new SkillVo();
        BeanUtils.copyProperties(skillInfo, vo);

        // 查询发布者信息
        FeignWxUserDto userDto = wxUserApiFeign.selectFeignWxUserDtoByWxUserId(skillInfo.getUserId());
        vo.setUserInfo(userDto);
        if (userDto != null) {
            vo.setIcon(userDto.getIcon());
            vo.setNickName(userDto.getNickname());
            vo.setDepartment(userDto.getOrganizationName());
        } else {
            vo.setNickName("未知");
            vo.setDepartment("未知");
            vo.setIcon("");
        }
        // 更新观看次数
        Skill saveSkill = new Skill();
        saveSkill.setId( skillInfo.getId() );
        saveSkill.setWatchNum( skillInfo.getWatchNum()+1 );
        skillMapper.updateById(saveSkill);

        // 更新观看记录
        if (userId!=null){
            Long watchId = skillVideoLogMapper.getLogByUser(id, userId);
            if (watchId==null){
                SkillVideoLog videoLog = new SkillVideoLog();
                videoLog.setWatchUserId(userId);
                videoLog.setSkillId(id);
                skillVideoLogMapper.insert(videoLog);
                log.info("用户{}观看了视频{}", userId, id);
            }
        }

        return new ReturnVO("查询成功", vo);
    }

    @Override
    public ReturnVO<JgPageVo<List<SkillVo>>> listSkill(SkillDto skillDto, Long enterpriseId, Long userId) {
        PageHelper.startPage(skillDto.getCurPage(), skillDto.getMaxPage());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("enterprise_id", enterpriseId);
        if (userId!=null){
            queryWrapper.eq("user_id", userId);
        }
        if ( skillDto.getSkillType()==null ){
            throw new ServiceException("请传入技能类型");
        }
        if (skillDto.getCategoryId()!=null && skillDto.getCategoryId()!=0){
            queryWrapper.eq("category_id",skillDto.getCategoryId());
        }
        queryWrapper.eq("skill_type", skillDto.getSkillType() );
        // 废弃审核状态的查询条件
        // if ( skillDto.getCheckStatus()!=null ) {
        //     queryWrapper.eq("check_status", skillDto.getCheckStatus() );
        // }
        if (StringUtils.isNotBlank( skillDto.getSkillTitle() )) {
            queryWrapper.like("skill_title", skillDto.getSkillTitle() + "%");
        }
        queryWrapper.orderByDesc("create_time");
        List<Skill> skills = skillMapper.selectList(queryWrapper);
        List<SkillVo> skillVos = new ArrayList<>();

        // foreach
        for (Skill skill: skills) {
            // user feign
            SkillVo vo = new SkillVo();
            BeanUtils.copyProperties(skill, vo);
            // 根据用户查询 查询发布者信息
            FeignWxUserDto userDto = wxUserApiFeign.selectFeignWxUserDtoByWxUserId(skill.getUserId());
            vo.setUserInfo(userDto);
            if (userDto != null) {
                vo.setNickName(userDto.getNickname());
                vo.setDepartment(userDto.getOrganizationName());
                vo.setIcon(userDto.getIcon());
            } else {
                vo.setNickName("未知");
                vo.setDepartment("未知");
                vo.setIcon("");
            }
            skillVos.add(vo);
        }

        return new ReturnVO("查询成功", new JgPageVo<>(new PageInfo(skillVos)));
    }

    @Override
    public ReturnVO<JgPageVo<List<SkillPublishVo>>> listSkillPublishRank(SkillPublishDto skillPublishDto, Long enterpriseId) {
        PageHelper.startPage(skillPublishDto.getCurPage(), skillPublishDto.getMaxPage());

        List<Skill> skills = skillMapper.getRank(enterpriseId);
        List<SkillPublishVo> skillPublishVos = new ArrayList<>();

        // foreach
        for (Skill skill: skills) {
            // user feign
            SkillPublishVo vo = new SkillPublishVo();
            BeanUtils.copyProperties(skill, vo);
            FeignWxUserDto feignWxUserDto = wxUserApiFeign.selectFeignWxUserDtoByWxUserId(skill.getUserId());
            vo.setNickName(feignWxUserDto.getNickname());
            vo.setDepartment(feignWxUserDto.getOrganizationName());
            vo.setIcon(feignWxUserDto.getIcon());
            vo.setPublishNum(skill.getWatchNum());
            skillPublishVos.add(vo);
        }
        return new ReturnVO("查询成功", new JgPageVo<>(new PageInfo(skillPublishVos)));
    }


    @Autowired
    private CommentProducer commentProducer;

    @Override
    public ReturnVO deleteSkill(Long id, Long userId, Long enterpriseId, Boolean isBackend) {
        Skill skillInfo = skillMapper.selectById(id);
        if (skillInfo==null)
            throw new ServiceException("请选择正确的技能");
        if (isBackend){
            // 后台删除
            // 检查企业
            if (!enterpriseId.equals(skillInfo.getEnterpriseId())){
                throw new ServiceException("暂无删除该技能的权限");
            }
        }else{
            // 用户删除
            // 检查用户
            if (!userId.equals(skillInfo.getUserId())){
                throw new ServiceException("暂无删除该技能的权限");
            }
            //todo 小程序订阅
            SystemMessageMqDto systemMessageMqDto = new SystemMessageMqDto();
            systemMessageMqDto.setMessageDetail("很抱歉,您发布的:" + skillInfo.getSkillTitle() + "技能沉淀因违规已被管理员删除");
            systemMessageMqDto.setMessageTitle("技能沉淀");
            systemMessageMqDto.setWxUserIds(new ArrayList<Long>() {
                {
                    add(userId);
                }
            });
            commentProducer.ackMQSender(JSONObject.toJSONString(systemMessageMqDto));
        }
        skillMapper.deleteById(id);
        return new ReturnVO("删除成功", "");
    }

    @Override
    public ReturnVO saveComment(SkillComment comment) {
        Skill skillInfo = skillMapper.selectById(comment.getSkillId());
        if (skillInfo==null)
            throw new ServiceException("请选择正确的技能");

        comment.setCreateTime(LocalDateTime.now());
        SkillComment insert = mongoTemplate.insert(comment);
        // 增加 评论数量
        Skill saveSkill = new Skill();
        saveSkill.setId( skillInfo.getId() );
        saveSkill.setCommentNum( skillInfo.getCommentNum()+1 );
        skillMapper.updateById( saveSkill );

        return new ReturnVO("评论成功", insert.getUid());
    }

    @Override
    public ReturnVO<JgPageVo<List<SkillComment>>> listComment(SkillCommentDto skillCommentDto) {
        List<SkillComment> list = new ArrayList();
        Query query1 = new Query();
        String skillId = String.valueOf(skillCommentDto.getId());
        SkillComment comment = mongoTemplate.findById(skillId, SkillComment.class);
        query1.with(new Sort(Sort.Direction.DESC, "createTime")).with(new PageRequest(skillCommentDto.getCurPage()-1, skillCommentDto.getMaxPage()));
        query1.addCriteria(Criteria.where("skillId").is(skillCommentDto.getId())).addCriteria(Criteria.where("_id").ne(skillId));
        Query queryCount = new Query();
        queryCount.addCriteria(Criteria.where("skillId").is(skillCommentDto.getId()));
        long count = mongoTemplate.count(queryCount, "skillCommentCollection");
        list = mongoTemplate.find(query1, SkillComment.class);
//        if (skillCommentDto.getCurPage() == 1) {
//            if (list.size() != 1&&list.size()>9) {
//                list.remove(list.size() - 1);
//            }
//        }
        // FIXME: 修复第一个数值为null的问题
        JgPageVo jgPageVo = new JgPageVo<>(new PageInfo(list));
        jgPageVo.setCurIndex(skillCommentDto.getCurPage());
        jgPageVo.setPageSize(skillCommentDto.getMaxPage());
        jgPageVo.setPagesCount((int)Math.ceil(count*1.0/skillCommentDto.getMaxPage()));
        jgPageVo.setData(list);
        jgPageVo.setCount(count);
        return new ReturnVO("评论查询成功", jgPageVo);
    }
}
